/*
 * Project Name spring-boot-tools
 * File Name VersionRequestMappingHandlerMapping
 * Package Name com.huxiaosu.tools.common.version
 * Create Time 2024/7/16
 * Create by name：liujie
 */
package com.huxiaosu.tools.common.version;

import com.huxiaosu.tools.common.annotation.ApiVersion;
import com.huxiaosu.tools.common.annotation.ClientVersion;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Description
 *
 * @author liujie
 * @date 2024/7/16 10:05
 */
public class VersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    // 重写此处，保证读取我们的注解 apiversion
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappinginfo = super.getMappingForMethod(method, handlerType);
        if (mappinginfo != null) {
            RequestMappingInfo apiVersionMappingInfo = getApiVersionMappingInfo(method, handlerType);
            if(apiVersionMappingInfo.getPathPatternsCondition() !=null){
                return apiVersionMappingInfo.combine(mappinginfo);
            }
            return mappinginfo;

        }
        return mappinginfo;
    }

    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ClientVersion.class);
        return createRequestCondition(clientVersion);
    }

    // 重新定义clientversion的条件匹配
    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(method, ClientVersion.class);
        return createRequestCondition(clientVersion);
    }

    private RequestCondition<?> createRequestCondition(ClientVersion clientVersion) {
        if (clientVersion == null) {
            return null;
        }
        if (clientVersion.value().length > 0) {
            return new VersionRequestCondition(clientVersion.value());
        }

        return null;
    }

    private RequestMappingInfo getApiVersionMappingInfo(Method method, Class<?> handlerType) {
        ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class);
        // 再次尝试类上的版本
        if (apiVersion == null) {
            apiVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ApiVersion.class);
        }
        RequestMappingInfo.Builder mappingInfoBuilder = RequestMappingInfo.paths("");
        if (apiVersion != null) {
            String[] values = { apiVersion.version() };
            mappingInfoBuilder = RequestMappingInfo.paths(values);
        }

        return mappingInfoBuilder.build();
    }

    @Override
    protected void handlerMethodsInitialized(Map<RequestMappingInfo, HandlerMethod> handlerMethods) {
        // 打印路由信息 spring boot 2.1 去掉了这个 日志的打印
        if (logger.isDebugEnabled()) {
            for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
                RequestMappingInfo mapping = entry.getKey();
                HandlerMethod handlerMethod = entry.getValue();
                logger.debug("Mapped \"" + mapping + "\" onto " + handlerMethod);
            }
        }
        super.handlerMethodsInitialized(handlerMethods);

    }
}